package com.mars.module.tool.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.mars.common.constant.Constant;
import com.mars.common.constant.GenConstants;
import com.mars.common.request.tool.GenCodeDeployRequest;
import com.mars.common.request.tool.GenCodeRemoveRequest;
import com.mars.common.response.PageInfo;
import com.mars.common.response.tool.TableListResponse;
import com.mars.common.util.*;
import com.mars.framework.config.GenConfig;
import com.mars.framework.context.ContextUserInfoThreadHolder;
import com.mars.framework.exception.ServiceException;
import com.mars.framework.handler.TransHandler;
import com.mars.framework.reader.ClassMethodReader;
import com.mars.framework.router.DynamicRoute;
import com.mars.module.system.entity.BaseEntity;
import com.mars.module.tool.entity.*;
import com.mars.module.tool.mapper.*;
import com.mars.module.tool.request.*;
import com.mars.module.tool.response.GenTableResponse;
import com.mars.module.tool.service.ISysMenuGenService;
import com.mars.module.tool.service.ITableGenerationService;

import com.mars.router.RouterController;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.sql.DataSource;
import javax.sql.rowset.serial.SerialException;
import java.io.*;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 业务 服务层实现
 *
 * @author mars
 */
@Service
@SuppressWarnings("all")
public class TableGenerationServiceImpl implements ITableGenerationService {
    private static final Logger log = LoggerFactory.getLogger(TableGenerationServiceImpl.class);

    @Resource
    private DataSource dataSource;

    @Resource
    private GenTableMapper genTableMapper;

    @Resource
    private GenTableColumnMapper genTableColumnMapper;

    @Resource
    private GenControllerMethodsMapper genControllerMethodsMapper;

    @Resource
    private GenSysMenuMapper genSysMenuMapper;

    @Resource
    private GenConfig genConfig;

    @Resource
    private ClassMethodReader classMethodReader;

    @Resource
    private ISysMenuGenService genSysMenuService;

    @Resource
    private DynamicRoute dynamicRoute;

    @Resource
    private GenCreateTableRecordMapper createTableRecordMapper;

    public static final String SRC = "/src";

    @Resource
    private GenUtils genUtils;

    /**
     * 查询业务信息
     *
     * @param id 业务ID
     * @return 业务信息
     */
    @Override
    public GenTable selectGenTableById(Long id) {
        GenTable genTable = genTableMapper.selectById(id);
        setTableFromOptions(genTable);
        return genTable;
    }

    /**
     * 查询业务列表
     *
     * @param genTable 业务信息
     * @return 业务集合
     */
    @Override
    public List<GenTable> selectGenTableList(GenTable genTable) {
        return genTableMapper.selectGenTableList(genTable);
    }

    /**
     * 查询据库列表
     *
     * @param genTable 业务信息
     * @return 数据库表集合
     */
    @Override
    public List<GenTable> selectDbTableList(GenTable genTable) {
        return genTableMapper.selectDbTableList(genTable);
    }

    /**
     * 查询据库列表
     *
     * @param tableNames 表名称组
     * @return 数据库表集合
     */
    @Override
    public List<TableListResponse> selectDbTableListByNames(List<String> tableNames) {
        return genTableMapper.selectDbTableListByTableNames(tableNames);
    }

    /**
     * 修改业务
     *
     * @param genTable 业务信息
     * @return 结果
     */
    @Override
    @Transactional
    public void updateGenTable(GenTable genTable) {
        String options = JSON.toJSONString(genTable.getParams());
        genTable.setOptions(options);
        int row = genTableMapper.updateById(genTable);
        if (row > 0) {
            if (!CollectionUtils.isEmpty(genTable.getGenTableColumnList())) {
                for (GenTableColumn cenTableColumn : genTable.getGenTableColumnList()) {
                    genTableColumnMapper.alwaysUpdateSomeColumnById(cenTableColumn);
                }
            }

        }
    }

    /**
     * 删除业务对象
     *
     * @param tableIds 需要删除的数据ID
     * @return 结果
     */
    @Override
    @Transactional
    public void deleteGenTableByIds(Long[] tableIds) {
        genTableMapper.deleteBatchIds(Arrays.asList(tableIds));
        genTableColumnMapper.delete(Wrappers.lambdaQuery(GenTableColumn.class).in(GenTableColumn::getTableId, Arrays.asList(tableIds)));
    }

    /**
     * 导入表结构
     *
     * @param request request
     */
    @Override
    public void importGenTable(GenTableImportRequest request) {
        if (CollectionUtils.isEmpty(request.getTableNames())) {
            throw new ServiceException("请选择表名称");
        }
        String operateName = ContextUserInfoThreadHolder.get().getUserName();
        List<String> tableNames = request.getTableNames();
        for (String tableName : tableNames) {
            GenTable genTable = new GenTable();
            genTable.setTableName(tableName);
            //查看是否已存在，存在删除重新执行导入
            List<GenTable> genTables = this.selectGenTableList(genTable);
            if (!CollectionUtils.isEmpty(genTables)) {
                GenTable genTable1 = genTables.get(0);
                this.deleteGenTableById(genTable1.getTableId());
            }
        }
        List<TableListResponse> tableList = this.selectDbTableListByNames(tableNames);
        for (TableListResponse response : tableList) {
            GenTable table = new GenTable();
            BeanUtils.copyProperties(response, table);
            String tableName = table.getTableName();
            genUtils.initTable(table, operateName);
            genTableMapper.insert(table);
            // 保存列信息
            List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
            List<GenTableColumn> columnList = genTableColumns.stream().peek(x -> {
                GenUtils.initColumnField(x, table);
                x.setDeleted(0);
            }).collect(Collectors.toList());
            genTableColumnMapper.insertBatchSomeColumn(columnList);
            // 保存控制器方法
            GenControllerMethods methods = new GenControllerMethods();
            methods.setTableId(table.getTableId());
            genControllerMethodsMapper.insert(methods);
        }

    }

    /**
     * 预览代码
     *
     * @param tableId 表编号
     * @return 预览数据列表
     */
    @Override
    public Map<String, String> previewCode(Long tableId) {
        Map<String, String> dataMap = new LinkedHashMap<>();
        // 查询表信息
        GenTable table = genTableMapper.selectById(tableId);
        // 查询列信息
        List<GenTableColumn> columns = table.getColumns();
        setPkColumn(table, columns);
        VelocityInitializer.initVelocity();

        VelocityContext context = VelocityUtils.prepareContext(table);

        // 获取模板列表
        List<String> templates = VelocityUtils.getTemplateList(table);
        for (String template : templates) {
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, Constant.UTF8);
            tpl.merge(context, sw);
            dataMap.put(template, sw.toString());
        }
        return dataMap;
    }

    /**
     * 生成代码
     *
     * @param tableName 表名称
     * @return 数据
     */
    @Override
    public byte[] generatorCode(String tableName) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        generatorCode(tableName, zip);
        IOUtils.closeQuietly(zip);
        return outputStream.toByteArray();
    }

    /**
     * 批量生成代码
     *
     * @param tableNames 表数组
     * @return 数据
     */
    @Override
    public byte[] generatorCode(String[] tableNames) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        for (String tableName : tableNames) {
            generatorCode(tableName, zip);
        }
        IOUtils.closeQuietly(zip);
        return outputStream.toByteArray();
    }

    /**
     * 查询表信息并生成代码
     */
    private void generatorCode(String tableName, ZipOutputStream zip) {
        // 查询表信息
        GenTable table = genTableMapper.selectOne(Wrappers.lambdaQuery(GenTable.class).eq(GenTable::getTableName, tableName));
        // 查询列信息
        List<GenTableColumn> columns = table.getColumns();
        setPkColumn(table, columns);

        VelocityInitializer.initVelocity();

        VelocityContext context = VelocityUtils.prepareContext(table);

        // 获取模板列表
        List<String> templates = VelocityUtils.getTemplateList(table);
        for (String template : templates) {
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, Constant.UTF8);
            tpl.merge(context, sw);
            try {
                // 添加到zip
                zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table)));
                IOUtils.write(sw.toString(), zip, Constant.UTF8);
                IOUtils.closeQuietly(sw);
                zip.flush();
                zip.closeEntry();
            } catch (IOException e) {
                log.error("渲染模板失败，表名：" + table.getTableName(), e);
            }
        }
    }

    /**
     * 修改保存参数校验
     *
     * @param genTable 业务信息
     */
    @Override
    public void validateEdit(GenTable genTable) {
        if (GenConstants.TPL_TREE.equals(genTable.getTplCategory())) {
            String options = JSON.toJSONString(genTable.getParams());
            JSONObject paramsObj = JSONObject.parseObject(options);
            if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_CODE))) {
                throw new ServiceException("树编码字段不能为空");
            } else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_PARENT_CODE))) {
                throw new ServiceException("树父编码字段不能为空");
            } else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_NAME))) {
                throw new ServiceException("树名称字段不能为空");
            }
        }
    }


    /**
     * 设置主键列信息
     *
     * @param table 业务表信息
     */
    public void setPkColumn(GenTable table) {
        for (GenTableColumn column : table.getColumns()) {
            if (column.isPk()) {
                table.setPkColumn(column);
                break;
            }
        }
        if (StringUtil.isNull(table.getPkColumn())) {
            table.setPkColumn(table.getColumns().get(0));
        }
        if (GenConstants.TPL_SUB.equals(table.getTplCategory())) {
            for (GenTableColumn column : table.getSubTable().getColumns()) {
                if (column.isPk()) {
                    table.getSubTable().setPkColumn(column);
                    break;
                }
            }
            if (StringUtil.isNull(table.getSubTable().getPkColumn())) {
                table.getSubTable().setPkColumn(table.getSubTable().getColumns().get(0));
            }
        }
    }

    /**
     * 设置主子表信息
     *
     * @param table 业务表信息
     */
    public void setSubTable(GenTable table) {
        if (StringUtil.isNotEmpty(table.getSubTableName())) {
            String subTableName = table.getSubTableName();
            if (StringUtils.isNotEmpty(subTableName)) {
                table.setSubTable(genTableMapper.selectGenTableByName(subTableName));
            }
        }
    }


    /**
     * 生成代码（自定义路径）
     *
     * @param tableName 表名称
     * @param genPath   生成的路径
     */
    public GenTable generatorCode(String tableName, String genPath) {
        // 查询表信息
        GenTable table = genTableMapper.selectGenTableByName(tableName);
        // 设置主子表信息
        setSubTable(table);
        // 设置主键列信息
        setPkColumn(table);
        //强制设置生成目录
        this.operateDir(genPath, table);
        // 设置是否生成基础字段
        setGenBaseField(table);
        // 设置菜单存放位置
        VelocityInitializer.initVelocity();
        VelocityContext context = VelocityUtils.prepareContext(table);
        // 获取模板列表
        List<String> templates = VelocityUtils.getTemplateList(table);
        //是否输出所有文件，包含前端，后端
        this.writeStringToFile(table, context, templates);
        return table;
    }

    private void writeStringToFile(GenTable table, VelocityContext context, List<String> templates) {
        for (String template : templates) {
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, Constant.UTF8);
            tpl.merge(context, sw);
            try {
                String path = getGenPath(table, template);
                FileUtils.writeStringToFile(new File(path), sw.toString(), CharsetKit.UTF_8);
            } catch (IOException e) {
                throw new ServiceException("渲染模板失败，表名：" + table.getTableName());
            }
        }
    }

    private void operateDir(String genPath, GenTable table) {
        if (genPath != null && !"".equals(genPath)) {
            table.setGenType("1");
            table.setGenPath(genPath);
            //强制删除目录中之前的所有文件
            File genPathDir = new File(genPath);
            if (genPathDir.exists()) {
                if (genPathDir.isDirectory()) {
                    for (File f : Objects.requireNonNull(genPathDir.listFiles())) {
                        if (f.isDirectory()) {
                            try {
                                FileUtils.deleteDirectory(f);
                            } catch (IOException exception) {
                                exception.printStackTrace();
                            }
                        } else {
                            f.delete();
                        }
                    }
                }
            } else {
                //目录不存在，则创建目录
                genPathDir.mkdirs();
            }
        }
    }

    /**
     * 设置是否生成基础字段
     *
     * @param table table
     */
    private void setGenBaseField(GenTable table) {
        List<GenCreateTableRecord> createTableRecords = createTableRecordMapper.selectList(Wrappers.lambdaQuery(GenCreateTableRecord.class)
                .eq(GenCreateTableRecord::getTableEnName, table.getTableName()).orderByDesc(BaseEntity::getCreateTime).last("limit 1"));
        if (!CollectionUtils.isEmpty(createTableRecords)) {
            Integer genBaseField = createTableRecords.get(0).getGenBaseField();
            if (genBaseField == 0) {
                // 生成基础字段 列信息去掉基础字段重新赋值
                List<GenTableColumn> columns = table.getColumns();
                Iterator<GenTableColumn> iterator = columns.iterator();
                while (iterator.hasNext()) {
                    GenTableColumn column = iterator.next();
                    if (Arrays.asList(GenConstants.COLUMNNAME_NOT_BASE_ENTITY).contains(column.getColumnName())) {
                        iterator.remove();
                    }
                }
                table.setColumns(columns);
                table.setGenBaseField(true);
            }
        } else {
            // 不生成基础字段 列信息去掉基础字段重新赋值
            boolean isGenBaseField = false;
            List<GenTableColumn> columns = table.getColumns();
            Iterator<GenTableColumn> iterator = columns.iterator();
            while (iterator.hasNext()) {
                GenTableColumn column = iterator.next();
                if (Arrays.asList(GenConstants.COLUMNNAME_NOT_LIST).contains(column.getColumnName()) && !column.getColumnName().equals("create_time")) {
                    isGenBaseField = true;
                    iterator.remove();
                }
            }
            table.setColumns(columns);
            table.setGenBaseField(isGenBaseField);
        }
    }


    /**
     * 获取代码生成地址
     *
     * @param table    业务表信息
     * @param template 模板文件路径
     * @return 生成地址
     */
    public static String getGenPath(GenTable table, String template) {
        String genPath = table.getGenPath();
        if (StringUtils.equals(genPath, "/")) {
            return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table);
        }
        return genPath + "/" + VelocityUtils.getFileName(template, table);
    }


    @Override
    public void deploy(GenCodeDeployRequest request) {
        if (CollectionUtils.isEmpty(request.getTableName())) {
            throw new ServiceException("请选择部署表结构");
        }
        // 生成代码的目录
        String generatorCodePath = genConfig.getGeneratorCodePath();
        // Java后台的Src目录
        String javaDir = genConfig.getServerCodeDir() + SRC;
        String htmlDir = genConfig.getHtmlCodeDir() + SRC;
        for (String tableName : request.getTableName()) {
            GenTable genTable = this.generatorCode(tableName, generatorCodePath);
            // 自动复制后台代码
            this.copyServerCode(generatorCodePath, javaDir);
            // 自动复制前台代码
            this.copyWebUiCode(genTable.getModuleName(), generatorCodePath, htmlDir);
            //  保存菜单
            this.saveSysMenu(genTable.getModuleName(), genTable.getFunctionName(), underlineToCamel(genTable.getTableName()), request, genTable.getTableName());
            // 生成路由
            this.genDynamicRouter(genTable.getModuleName(), underlineToCamel(genTable.getTableName()));

        }
    }

    /**
     * 动态生成路由
     *
     * @param businessName businessName
     */
    private void genDynamicRouter(String moduleName, String businessName) {
        // 反射获取路由名称
        List<String> list = classMethodReader.readClassMethods(RouterController.class);
        if (!list.contains(moduleName + firstLetterName(businessName))) {
            dynamicRoute.writeRouter(moduleName, businessName);
        }
    }


    /**
     * 后台代码复制
     *
     * @param generatorCodePath generatorCodePath
     * @param javaSrc           javaSrc
     */
    private void copyServerCode(String generatorCodePath, String javaSrc) {
        File srcFile = new File(generatorCodePath + "/" + "main");
        //复制到的目录
        File destFile = new File(javaSrc + "/" + "main");
        try {
            FileUtils.copyDirectory(srcFile, destFile);
            System.out.println("------后台代码构建成功--------");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 复制前端代码
     *
     * @param generatorCodePath generatorCodePath
     * @param htmlSrc           htmlSrc
     */
    private void copyWebUiCode(String moduleName, String generatorCodePath, String htmlSrc) {
        File uiSrcFile = new File(generatorCodePath + "/" + "web/html");
        //复制到的目录
        File uiDestFile = new File(htmlSrc + "/main/resources/pages/" + moduleName);
        try {
            FileUtils.copyDirectory(uiSrcFile, uiDestFile);
            System.out.println("------前端代码生成成功--------");
        } catch (IOException e) {
            e.printStackTrace();
        }

        File jsSrcFile = new File(generatorCodePath + "/" + "web/api");
        //复制到的目录
        File jsDestFile = new File(htmlSrc + "/main/resources/static/api/" + moduleName);
        try {
            FileUtils.copyDirectory(jsSrcFile, jsDestFile);
            System.out.println("------js代码生成成功--------");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(GenCodeRemoveRequest request) {
        if (CollectionUtils.isEmpty(request.getTableName())) {
            throw new ServiceException("请选择卸载表结构");
        }

        //生成代码的目录
        String generatorCodePath = genConfig.getGeneratorCodePath();
        //Java后台的Src目录
        String javaSrc = genConfig.getServerCodeDir() + SRC;
        //前端html
        String htmlSrc = genConfig.getHtmlCodeDir() + SRC;
        for (String tableName : request.getTableName()) {
            //生成当前模块的代码，用于后续的比较
            GenTable genTable = this.generatorCode(tableName, generatorCodePath);
            // 删除后台代码
            this.removeServerCode(generatorCodePath, javaSrc);
            //被复制的文件夹 自动复制前台代码
//            this.removeWebCode(generatorCodePath, htmlSrc);
            // 移除菜单
            this.removeMenu(tableName);
            // 删除路由
            this.removeDynamicRoute(underlineToCamel(genTable.getTableName()));
        }
    }

    /**
     * 删除动态路由
     *
     * @param businessName businessName
     */
    private void removeDynamicRoute(String businessName) {
//        DynamicRoute.remove(businessName);
    }

    /**
     * 删除菜单
     *
     * @param genTable
     */
    private void removeMenu(String tableName) {
        // 判断当前菜单是否只有一个 只有一个删除自己和父菜单  多个的话删除自己
        List<GenSysMenu> genSysMenus = genSysMenuMapper.selectMenuListByName(tableName);
        // 获取菜单
        if (!CollectionUtils.isEmpty(genSysMenus)) {
            List<GenSysMenu> menus = genSysMenus.stream().filter(x -> x.getMenuType() == 2).collect(Collectors.toList());
            // 菜单只有一个
            GenSysMenu genSysMenu = menus.get(0);
            Long parentId = genSysMenu.getParentId();
            // 根据父ID查询子菜单
            List<GenSysMenu> menuList = genSysMenuMapper.selectMenuListByParentId(parentId);
            if (menuList.size() == 1) {
                // 只有一个删除自己以及子按钮权限和父菜单
                List<Long> menuIds = genSysMenus.stream().map(GenSysMenu::getId).collect(Collectors.toList());
                genSysMenuMapper.deleteBatchIds(menuIds);
            } else {
                // 只删除自己以及子按钮权限 过滤父菜单
                List<GenSysMenu> list = genSysMenus.stream().filter(x -> x.getMenuType() != 1).collect(Collectors.toList());
                List<Long> menuIds = list.stream().map(GenSysMenu::getId).collect(Collectors.toList());
                genSysMenuMapper.deleteBatchIds(menuIds);
            }
        }
    }

    @Override
    public void saveSysMenu(String moduleName, String functionName, String businessName, GenCodeDeployRequest request, String tableName) {
        GenSysMenuRequest parentMenuRequest = new GenSysMenuRequest();
        if (Objects.isNull(request.getType())) {
            request.setType(1);
        }
        if (request.getType() == 1) {
            parentMenuRequest.setMenuType(1);
            parentMenuRequest.setIcon("el-icon-notebook-2");
            parentMenuRequest.setParentId(0L);
            parentMenuRequest.setMenuName(functionName + "管理");
            Integer maxSort = genSysMenuService.selectMaxSort(1, null);
            parentMenuRequest.setSort(maxSort);
            parentMenuRequest.setUrl("#");
            // 设置菜单
            GenSysMenuRequest menuRequest = new GenSysMenuRequest();
            menuRequest.setIcon("el-icon-notebook-2");
            menuRequest.setMenuType(2);
            menuRequest.setMenuName(functionName + "列表");
            menuRequest.setUrl(moduleName + "/" + businessName + "/" + businessName + ".html");
            parentMenuRequest.setChildren(Collections.singletonList(menuRequest));
            // 设置按钮菜单
            List<GenSysMenuRequest> childButtonMenuList = this.getButtonMenuList(moduleName, functionName, businessName);
            menuRequest.setChildren(childButtonMenuList);
        } else {
            parentMenuRequest.setMenuType(2);
            // 根据目录菜单ID查询目录
            GenSysMenu dirMenu = genSysMenuMapper.selectById(request.getMenuId());
            parentMenuRequest.setIcon("el-icon-notebook-2");
            parentMenuRequest.setParentId(dirMenu.getId());
            parentMenuRequest.setMenuName(functionName + "列表");
            Integer maxSort = genSysMenuService.selectMaxSort(2, dirMenu.getId());
            parentMenuRequest.setSort(maxSort);
            parentMenuRequest.setUrl(moduleName + "/" + businessName + "/" + businessName + ".html");
            // 设置按钮菜单
            List<GenSysMenuRequest> childMenuList = this.getButtonMenuList(moduleName, functionName, businessName);
            parentMenuRequest.setChildren(childMenuList);
        }
        genSysMenuService.saveGenMenu(parentMenuRequest, functionName, tableName);


    }


    @Override
    public PageInfo<GenTableResponse> genTableList(GenTableRequest request) {
        LambdaQueryWrapper<GenTable> wrapper = Wrappers.lambdaQuery(GenTable.class)
                .like(StringUtil.isNotEmpty(request.getTableName()), GenTable::getTableName, request.getTableName())
                .like(StringUtil.isNotEmpty(request.getTableComment()), GenTable::getTableComment, request.getTableComment())
                .orderByDesc(BaseEntity::getCreateTime);
        IPage<GenTableResponse> page = genTableMapper.selectPage(request.page(), wrapper).convert(x -> {
            GenTableResponse response = new GenTableResponse();
            BeanUtils.copyProperties(x, response);
            if (Objects.nonNull(x.getGenMenuType())) {
                response.setGenMenuType(x.getGenMenuType().toString());
            }
            return response;
        });
        return PageInfo.build(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteGenTableById(Long id) {
        genTableMapper.deleteById(id);
        // 删除从表
        genTableColumnMapper.delete(Wrappers.lambdaQuery(GenTableColumn.class).eq(GenTableColumn::getTableId, id));
    }

    @Override
    public GenTableResponse detail(Long id) {
        GenTable genTable = genTableMapper.selectById(id);
        if (Objects.isNull(genTable)) {
            throw new ServiceException("查询导入表失败");
        }
        GenTableResponse response = new GenTableResponse();
        BeanUtils.copyProperties(genTable, response);
        if (Objects.nonNull(genTable.getGenMenuType())) {
            response.setGenMenuType(genTable.getGenMenuType().toString());
        }
        // 查询列信息
        List<GenTableColumn> tableColumnList = genTableColumnMapper.selectGenTableColumnListByTableId(id);
        response.setGenTableColumnList(tableColumnList);
        GenControllerMethods genControllerMethods = genControllerMethodsMapper.selectOne(Wrappers.lambdaQuery(GenControllerMethods.class)
                .eq(GenControllerMethods::getTableId, id));
        response.setGenControllerMethods(genControllerMethods);
        return response;
    }

    @Override
    public void createTable(CreateTableRequest request) throws SQLException {
        this.checkParams(request);
        // 根据英文名称查询数据库是否已存在改表
        List<TableListResponse> list = genTableMapper.selectDbTableListByTableNames(Collections.singletonList(request.getTableEnName()));
        if (!CollectionUtils.isEmpty(list)) {
            throw new ServiceException("当前表已创建");
        }
        // 创建表
        List<FieldRequest> fieldRequestList = request.getFieldRequestList().stream().peek(s -> {
            s.setFieldComment(s.getFieldName());
            String fieldName = s.getFieldName();
            if (isChinese(fieldName)) {
                String enFieldName = TransHandler.trans(fieldName);
                s.setFieldName(enFieldName);
            } else {
                s.setFieldName(fieldName);
                String chineseComment = TransHandler.trans(fieldName);
                s.setFieldComment(chineseComment);
            }
        }).collect(Collectors.toList());
        String tableDdl = SqlGeneratorUtils.generateDynamicSQL(fieldRequestList, request.getTableEnName(), request.isGenBaseField(), request.getTableName());
        // 执行建表语句
        this.doExecuteSql(tableDdl);
        // 保存生成记录
        GenCreateTableRecord createTableRecord = new GenCreateTableRecord();
        createTableRecord.setTableEnName(request.getTableEnName());
        createTableRecord.setTableName(request.getTableName());
        boolean genBaseField = request.isGenBaseField();
        createTableRecord.setGenBaseField(genBaseField ? 0 : 1);
        createTableRecordMapper.insert(createTableRecord);
    }

    /**
     * 判断是否是中文
     *
     * @param str str
     * @return boolean
     */
    public static boolean isChinese(String str) {
        // 使用正则表达式匹配是否全为中文字符
        return str.matches("[\\u4E00-\\u9FA5]+");
    }


    /**
     * 参数校验
     *
     * @param request request
     * @throws SerialException
     */
    private void checkParams(CreateTableRequest request) throws SerialException {
        if (StringUtil.isEmpty(request.getTableEnName())) {
            throw new SerialException("表中文名称不能为空");
        }
        if (StringUtil.isEmpty(request.getTableEnName())) {
            throw new SerialException("表英文名称不能为空");
        }
        if (CollectionUtils.isEmpty(request.getFieldRequestList())) {
            throw new ServiceException("表字段不能为空");
        }
    }


    /**
     * 执行SQL脚本
     *
     * @param sql sql
     */
    public void doExecuteSql(String sql) throws SQLException {
        Connection connection = DataSourceUtils.getConnection(dataSource);
        Statement statement = connection.createStatement();
        statement.execute(sql);
        statement.close();
        connection.close();
    }

    private List<GenSysMenuRequest> getButtonMenuList(String moudleName, String functionName, String businessName) {
        List<GenSysMenuRequest> buttonMenu = new ArrayList<>();

        GenSysMenuRequest listSysMenu = new GenSysMenuRequest();
        listSysMenu.setMenuName(functionName + "列表");
        listSysMenu.setIcon("el-icon-notebook-2");
        listSysMenu.setMenuType(3);
        listSysMenu.setUrl(moudleName + "/" + businessName + "/pageList");
        listSysMenu.setSort(1);

        GenSysMenuRequest addSysMenu = new GenSysMenuRequest();
        addSysMenu.setMenuName(functionName + "添加");
        addSysMenu.setIcon("el-icon-notebook-2");
        addSysMenu.setMenuType(3);
        addSysMenu.setUrl(moudleName + "/" + businessName + "/add");
        addSysMenu.setSort(1);

        GenSysMenuRequest updateSysMenu = new GenSysMenuRequest();
        updateSysMenu.setMenuName(functionName + "修改");
        updateSysMenu.setIcon("el-icon-notebook-2");
        updateSysMenu.setMenuType(3);
        updateSysMenu.setUrl(moudleName + "/" + businessName + "/update");
        updateSysMenu.setSort(1);

        GenSysMenuRequest deleteSysMenu = new GenSysMenuRequest();
        deleteSysMenu.setMenuName(functionName + "删除");
        deleteSysMenu.setIcon("el-icon-notebook-2");
        deleteSysMenu.setMenuType(3);
        deleteSysMenu.setUrl(moudleName + "/" + businessName + "/delete");
        deleteSysMenu.setSort(1);

        buttonMenu.add(addSysMenu);
        buttonMenu.add(listSysMenu);
        buttonMenu.add(updateSysMenu);
        buttonMenu.add(deleteSysMenu);
        return buttonMenu;
    }

    /**
     * 删除后台代码
     *
     * @param generatorCodePath generatorCodePath
     * @param javaSrc           javaSrc
     */
    private void removeServerCode(String generatorCodePath, String javaSrc) {
        File srcFile = new File(generatorCodePath + "/" + "main");
        //复制到的目录
        File destFile = new File(javaSrc + "/" + "main");

        //后端代码的文件列表
        List<String> javaSrcFileList = new ArrayList<>();
        try {
            System.out.println("------后台代码卸载成功--------");
            System.out.println("------java源码对照的文件夹--------" + srcFile.getPath());
            System.out.println("------卸载的项目路径--------" + destFile.getPath());
            //输出所有要删除的文件
            scanFile2List(srcFile, javaSrcFileList);
            System.out.println("-----------后端删除文件列表----------");
            for (String f : javaSrcFileList) {
                //相对路径
                String xdlj = f.substring(generatorCodePath.length(), f.length());
                //拼出项目中源码的绝对路径
                //拼出项目中源码的绝对路径
                String realJavaFileStr = javaSrc + xdlj;
                System.out.println(realJavaFileStr);
                File realJavaFile = new File(realJavaFileStr);
                realJavaFile.delete();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除前端代码
     *
     * @param generatorCodePath generatorCodePath
     * @param htmlSrc           htmlSrc
     * @return String
     */
    private void removeWebCode(String generatorCodePath, String htmlSrc) {
        File uiDestFile = new File(htmlSrc + "/main/resources/templates");
        //前端代码的文件列表
        List<String> htmlSrcFileList = new ArrayList<>();
        try {
            //输出所有要删除的文件
            scanFile2List(uiDestFile, htmlSrcFileList);
            System.out.println("-----------前端删除文件列表----------");
            for (String f : htmlSrcFileList) {
                //相对路径
                String xdlj = f.substring(generatorCodePath.length() + 4, f.length());
                //拼出项目中源码的绝对路径
                String realVueFileStr = htmlSrc + xdlj;
                System.out.println(realVueFileStr);
                File realVueFile = new File(realVueFileStr);
                realVueFile.delete();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 扫描目录下
     *
     * @param file     目录路径
     * @param fileList 保存文件列表
     */
    public static void scanFile2List(File file, List<String> fileList) {
        // 当前的路径是一个目录
        if (file.isDirectory()) {
            File[] list = file.listFiles((f) -> f.isDirectory() || !f.isDirectory());
            for (File temp : list) {
                // 递归操作，继续列出
                scanFile2List(temp, fileList);
            }
        } else {
            fileList.add(file.getPath());
        }
    }


    /**
     * 设置主键列信息
     *
     * @param table   业务表信息
     * @param columns 业务字段列表
     */
    public void setPkColumn(GenTable table, List<GenTableColumn> columns) {
        for (GenTableColumn column : columns) {
            if (column.isPk()) {
                table.setPkColumn(column);
                break;
            }
        }
        if (StringUtil.isNull(table.getPkColumn())) {
            table.setPkColumn(columns.get(0));
        }
    }

    /**
     * 设置代码生成其他选项值
     *
     * @param genTable 设置后的生成对象
     */
    public void setTableFromOptions(GenTable genTable) {
        JSONObject paramsObj = JSONObject.parseObject(genTable.getOptions());
        if (StringUtil.isNotNull(paramsObj)) {
            String treeCode = paramsObj.getString(GenConstants.TREE_CODE);
            String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE);
            String treeName = paramsObj.getString(GenConstants.TREE_NAME);
            genTable.setTreeCode(treeCode);
            genTable.setTreeParentCode(treeParentCode);
            genTable.setTreeName(treeName);
        }
    }


    /**
     * 下划线转驼峰
     *
     * @param str str
     * @return Sring
     */
    public static String underlineToCamel(String str) {
        StringBuilder result = new StringBuilder();
        String[] words = str.split("_");
        for (String word : words) {
            if (result.length() == 0) {
                result.append(word.toLowerCase());
            } else {
                result.append(word.substring(0, 1).toUpperCase());
                result.append(word.substring(1).toLowerCase());
            }
        }
        return result.toString();
    }

    /**
     * 首字母转大写
     *
     * @param name name
     * @return String
     */
    public static String firstLetterName(String name) {
        name = name.substring(0, 1).toUpperCase() + name.substring(1);
        return name;
    }

}
